﻿using System.Data;
using System.Linq.Expressions;
using Model.CommonModel.PageModel;

using SqlSugar;

namespace Repository
{
    /// <summary>
    /// 基础仓储接口
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    public interface IBaseRepository<T> where T : class, new()
    {
        #region 添加
        int Add(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true);
        int Add(T t);

        /// <summary>
        /// 插入实体，可忽略指定列
        /// </summary>
        /// <param name="parm">实体</param>
        /// <param name="ignoreClumns">忽略指定列</param>
        /// <returns>插入之后的实体信息</returns>
        T AddIgnoreClum(T parm, Expression<Func<T, object>> ignoreClumns);

        //int InsertIgnoreNullColumn(T t);

        //int InsertIgnoreNullColumn(T t, params string[] columns);

        //int Insert(SqlSugarClient client, T t);

        //long InsertBigIdentity(T t);

        int Insert(List<T> t);
        //int Insert(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true);

        //int InsertIgnoreNullColumn(List<T> t);

        //int InsertIgnoreNullColumn(List<T> t, params string[] columns);

        //DbResult<bool> InsertTran(T t);

        //DbResult<bool> InsertTran(List<T> t);
        long InsertReturnBigIdentity(T t);
        //T InsertReturnEntity(T t);

        //T InsertReturnEntity(T t, string sqlWith = SqlWith.UpdLock);

        //bool ExecuteCommand(string sql, object parameters);

        //bool ExecuteCommand(string sql, params SugarParameter[] parameters);

        //bool ExecuteCommand(string sql, List<SugarParameter> parameters);

        #endregion 

        #region 跟新

        //bool UpdateEntity(T entity, bool ignoreNullColumns = false);

        bool Update(T entity, Expression<Func<T, bool>> expression);

        /// <summary>
        /// 只更新表达式的值
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        //bool Update(T entity, Expression<Func<T, object>> expression, bool ignoreAllNull = false);

        //bool Update(T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where);

        //bool Update(SqlSugarClient client, T entity, Expression<Func<T, object>> expression, Expression<Func<T, bool>> where);

        /// <summary>
        ///
        /// </summary>
        /// <param name="entity">T</param>
        /// <param name="list">忽略更新</param>
        /// <param name="isNull">Null不更新</param>
        /// <returns></returns>
        bool Update(T entity, List<string> list = null, bool isNull = true);

        bool Update(List<T> entity);
        bool Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns);

        #endregion update

        DbResult<bool> UseTran(Action action);

        DbResult<bool> UseTran(SqlSugarClient client, Action action);

        bool UseTran2(Action action);

        #region 删除

        int Delete(Expression<Func<T, bool>> expression);
        int Delete(object[] obj);
        int Delete(object id);
        bool DeleteTable();
        bool DeleteAll(List<T> ts);
        #endregion delete

        #region 查询
        /// <summary>
        /// 根据条件查询分页数据
        /// </summary>
        /// <param name="where"></param>
        /// <param name="parm"></param>
        /// <returns></returns>
        PagedInfo<T> GetPages(Expression<Func<T, bool>> where, PagerInfo parm);

        PagedInfo<T> GetPages(Expression<Func<T, bool>> where, PagerInfo parm, Expression<Func<T, object>> order, string orderEnum = "Asc");

        bool Any(Expression<Func<T, bool>> expression);

        ISugarQueryable<T> Queryable();
        List<T> GetAll(bool useCache = false, int cacheSecond = 3600);
        List<T> GetByIdList(object[] obj);

        //ISugarQueryable<ExpandoObject> Queryable(string tableName, string shortName);

        //ISugarQueryable<T, T1, T2> Queryable<T1, T2>() where T1 : class where T2 : new();

        List<T> GetList(Expression<Func<T, bool>> expression);

        //Task<List<T>> QueryableToListAsync(Expression<Func<T, bool>> expression);

        //string QueryableToJson(string select, Expression<Func<T, bool>> expressionWhere);

        //List<T> QueryableToList(string tableName);

        //(List<T>, int) QueryableToPage(Expression<Func<T, bool>> expression, int pageIndex = 0, int pageSize = 10);

        //(List<T>, int) QueryableToPage(Expression<Func<T, bool>> expression, string order, int pageIndex = 0, int pageSize = 10);

        //(List<T>, int) QueryableToPage(Expression<Func<T, bool>> expression, Expression<Func<T, object>> orderFiled, string orderBy, int pageIndex = 0, int pageSize = 10);

        //(List<T>, int) QueryableToPage(Expression<Func<T, bool>> expression, Bootstrap.BootstrapParams bootstrap);

        //List<T> SqlQueryToList(string sql, object obj = null);
        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        T GetFirst(Expression<Func<T, bool>> where);
        T GetId(object pkValue);

        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        //T GetFirst(string parm);

        int Count(Expression<Func<T, bool>> where);

        #endregion query

        #region Procedure

        DataTable UseStoredProcedureToDataTable(string procedureName, List<SugarParameter> parameters);

        (DataTable, List<SugarParameter>) UseStoredProcedureToTuple(string procedureName, List<SugarParameter> parameters);

        #endregion Procedure
        #region 增删改查基础操作

        /// <summary>
        /// 插入实体
        /// </summary>
        Task<int> InsertAsync(T entity);

        /// <summary>
        /// 批量插入
        /// </summary>
        Task<int> InsertRangeAsync(List<T> entities);

        /// <summary>
        /// 根据ID获取实体
        /// </summary>
        Task<T> GetByIdAsync(object id);

        /// <summary>
        /// 获取第一条满足条件的记录
        /// </summary>
        Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression);

        /// <summary>
        /// 更新实体
        /// </summary>
        Task<bool> UpdateAsync(T entity);

        /// <summary>
        /// 条件更新
        /// </summary>
        Task<bool> UpdateAsync(Expression<Func<T, bool>> whereExpression, Expression<Func<T, T>> updateExpression);

        /// <summary>
        /// 删除实体
        /// </summary>
        Task<bool> DeleteAsync(object id);

        /// <summary>
        /// 条件删除
        /// </summary>
        Task<int> DeleteAsync(Expression<Func<T, bool>> whereExpression);

        #endregion

        #region 查询操作

        /// <summary>
        /// 获取所有数据
        /// </summary>
        Task<List<T>> GetAllAsync(bool useCache = false, int cacheSeconds = 3600);

        /// <summary>
        /// 获取列表
        /// </summary>
        Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression);

        /// <summary>
        /// 分页查询
        /// </summary>
        Task<PagedInfo<T>> GetPagedListAsync(Expression<Func<T, bool>> whereExpression,
            int pageIndex = 1,
            int pageSize = 20,
            Expression<Func<T, object>> orderByExpression = null,
            OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 是否存在记录
        /// </summary>
        Task<bool> AnyAsync(Expression<Func<T, bool>> whereExpression);

        /// <summary>
        /// 获取数量
        /// </summary>
        Task<int> CountAsync(Expression<Func<T, bool>> whereExpression);

        #endregion

        #region 事务与存储过程

        /// <summary>
        /// 执行事务
        /// </summary>
        Task<bool> UseTransactionAsync(Func<Task> action);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        Task<DataTable> ExecuteStoredProcedureAsync(string procedureName, List<SugarParameter> parameters);

        /// <summary>
        /// 执行带输出参数的存储过程
        /// </summary>
        Task<(DataTable Result, List<SugarParameter> OutParameters)> ExecuteStoredProcedureWithOutputAsync(
            string procedureName,
            List<SugarParameter> parameters);

        #endregion
    }
}
